<script setup lang="ts">
import MultipleOperation from '@/components/MultipleOperation.vue'
import DialogRowView from './DialogRowView.vue'
import DialogRowAddEdit from './DialogRowAddEdit.vue'
import $mitt from '@/common/emitter'
import { useCommonStore } from '@/store/main'
import { tableDataInit, TABLE_DATA_SELECT_EVENT_FN, FORMAT_JSON_FOR_NOTES } from '@/common/hooks'
import { 
	INJECT_SYS_NAME, 
	INJECT_THEME_COLOR,
	INJECT_REQUEST_SUCCESS_NO
} from '@/common/provideType'
import { 
	serviceListRqs,
	serviceDycofigMainRqs,
	serviceDycofigGrayRqs,
	serviceDycofigMainAddRqs,
	serviceDycofigMainEditRqs,
	serviceDycofigGrayAddRqs,
	serviceDycofigGrayEditRqs,
	serviceDycofigMainDeleteRqs,
	serviceDycofigGrayDeleteRqs
} from '@/request/api'

import type { TableHeaderColumnsItemType, TableDataInitType } from '@/components/tableType'
import type { TabsPaneContext } from 'element-plus'
import type { DialogConfigType } from '@/components/dialogType'

const SYS_NAME = inject(INJECT_SYS_NAME)!
const THEME_COLOR = inject(INJECT_THEME_COLOR)!
const REQUEST_SUCCESS_NO = inject(INJECT_REQUEST_SUCCESS_NO)
const $store = useCommonStore()
const vPreventReClick = inject('vPreventReClick')
const vAuth = inject('vAuth')
const TAB_MAIN = 'tabMain'
const TAB_GRAY = 'tabGray'
const DIALOG_TYPE_VIEW = 'view'
const DIALOG_TYPE_ADD = 'add'
const DIALOG_TYPE_EDIT = 'edit'
const ZERO = 0
enum VERSION_TAB {
	main,
	gray
}
type TabType = {
	label: string
	name: string
	[property: string]: any
}
const tabs: TabType[] = [{
	label: '主版本',
	name: 'main'
}, {
	label: '灰度版本',
	name: 'gray'
}]

const dialogRef = ref()
const dialogRowViewRef = ref<InstanceType<typeof DialogRowView>>()
	const dialogAddEditRef = ref<InstanceType<typeof DialogRowAddEdit>>()

const tableHeaderColumnsMain: TableHeaderColumnsItemType[] = reactive([
	{label: 'Key', prop: 'key', width: 240},
	{label: 'Value', prop: 'value'}
])
const tableHeaderColumnsGray: TableHeaderColumnsItemType[] = reactive([
	{label: '实例ID', prop: 'instance_id', width: 240},
	{label: 'Key', prop: 'key', width: 240},
	{label: 'Value', prop: 'value'}
])
const tableData: TableDataInitType = reactive({
	...tableDataInit,
	lineHeightFlag: true,
	serialNumberHideFlag: true,
	tableMaxHeight: 600,
	operationConfig: {
		isShowFlag: true
	},
	isPreviewFlag: true,
	isEditFlag: true,
	isDeleteFlag: true,
	isMultipleOperationFlag: true
})

type RowType = typeof tableData.data[0]
type RowsType = RowType[]
type TabRecodeItemType = {
	currentPage: number
	pageSize: number
}
type TabRecodeType = {
	tabMain: TabRecodeItemType
	tabGray: TabRecodeItemType
}
type ServiceListType = {
	service_name: string
	deploy_type: number
	versionTab?: number
	tabRecode?: TabRecodeType
	[property: string]: any
}
type MainParamsType = {
	serviceName: string
	serviceIndex: number
	serviceList: ServiceListType[]
	[property: string]: any
}

const mainParams: MainParamsType = reactive({
	serviceList: [],
	serviceName: '',
	serviceIndex: -1,

	// tab 主版本/灰版本
	activeTab: 'main',

	// 新增按钮动图内容
	addServiceConfigName: '新增配置',
	successMessage: '',

	// 批量操作配置
	multipleConfig: [
		tableDataInit.multipleDelete
	]
})

// 请求服务列表
const queryServiceListFn = async () => {
	// 模拟返回结果
	const params = {sys_name: SYS_NAME}
	let res = await serviceListRqs(params)
	if(res?.code === REQUEST_SUCCESS_NO) {
		mainParams.serviceList = res.data!
		mainParams.serviceName = res.data[0].service_name
		mainParams.serviceIndex = 0
		mainParams.serviceList.forEach((item => {
			switch (item.deploy_type) {
				case 1:
					item.bgColor = 'success'
					break
				case 2:
					item.bgColor = 'warning'
					break
				case 3:
					item.bgColor = 'danger'
					break
			}

			// 分别给每个服务列表添加 versionTab 和 tabRecode 属性
			// versionTab，记录当前服务对应的 tab 状态
			// tabRecode，记录当前服务及  tab 对应的分页信息
			item.versionTab = VERSION_TAB.main
			item.tabRecode = {
				[TAB_MAIN]: {
					currentPage: tableData.currentPage, 
					pageSize: tableData.pageSize
				}, 
				[TAB_GRAY]: {
					currentPage: tableData.currentPage, 
					pageSize: tableData.pageSize
				}
			}
		}))

		// 初始化第一个服务对应的服务配置列表
		queryServiceConfigListFn(mainParams.serviceName)
	} 
}

/**
 * 请求服务配置
 * isInitFlag,  是否初始化
 * serviceName, 服务名
 * isTabCutFlag, 是否手动点击切换触发
 */
const queryServiceConfigListFn = async (serviceName: string) => {
	// 切换服务, 更新当前服务名，服务下标，tab名称
	if(mainParams.serviceName !== serviceName) {
		// 更新服务名及服务序号
		mainParams.serviceName = serviceName
		mainParams.serviceList.forEach(((item, index) => {
			if(item.service_name === serviceName) {
				mainParams.serviceIndex = index
				mainParams.activeTab = VERSION_TAB[item.versionTab!]
			}
		}))
	}
	
	const serviceItem = mainParams.serviceList[mainParams.serviceIndex]
	const isTabMainFlag = VERSION_TAB[serviceItem.versionTab!] === VERSION_TAB[0]
	const activeTabType = isTabMainFlag ? TAB_MAIN : TAB_GRAY
	let params = {
		sys_name: SYS_NAME,
		service_name: serviceName,
		page_no: serviceItem?.tabRecode?.[activeTabType].currentPage || tableData.currentPage,
		page_size: serviceItem?.tabRecode?.[activeTabType].pageSize || tableData.pageSize
	}

	const res = isTabMainFlag
		? await serviceDycofigMainRqs(params)
		: await serviceDycofigGrayRqs(params)

	if(res?.code === REQUEST_SUCCESS_NO) {
		tableData.data = res.data
		tableData.total = res.total!

		// 从 res.data 中抽出一个由 {value: tableData.data[item].key} 组成的数组，用于关联搜索
		const dealTableDataFn: DealTableDataFnType = data => data.map(item => ({value: item.key}))
		restaurants.value = dealTableDataFn(res.data)
		
		// 根据当前服务分页信息，更新 tableData 里的分页信息
		mainParams.serviceList.forEach((item => {
			if(item.service_name === serviceName) {
				let activeTabType: keyof TabRecodeType = TAB_MAIN
				activeTabType = isTabMainFlag ? TAB_MAIN : TAB_GRAY
				tableData.currentPage = item.tabRecode?.[activeTabType].currentPage!
				tableData.pageSize = item.tabRecode?.[activeTabType].pageSize!
			}
		}))
	}
}

// tab 版本切换
const tabHandleClick = (tab: TabsPaneContext) => {
	// 排除点击的是当前已选中的 tab 项
	if(tab.paneName !== mainParams.activeTab) {
		mainParams.addServiceConfigName = mainParams.addServiceConfigName === '新增配置' ? '新增灰度配置' : '新增配置'
		// mainParams.versionTab = tab.paneName === 'main' ? VERSION_TAB.MAIN : VERSION_TAB.GRAY
		// 更新 服务对应版本的实力数据
		if(typeof tab.paneName === 'string') {
			mainParams.serviceList.forEach((item => {
				if(item.service_name === mainParams.serviceName) {
					mainParams.activeTab = tab.paneName
					item.versionTab = VERSION_TAB[tab.paneName as keyof typeof VERSION_TAB]
				}
			}))
			queryServiceConfigListFn(mainParams.serviceName)
		}
	}
}

// 关联搜索
type RestaurantType = {
	value: string
	[property: string]: any
}
type DealTableDataFnType = {
	(params: RestaurantType[]): RestaurantType[]
}
const querySearchKey = ref('')
const restaurants = ref<RestaurantType[]>()
const querySearch = (queryString: string, cb: Function) => {
	const results = queryString 
		? restaurants.value?.filter(createFilter(queryString))
		: restaurants.value;
	cb(results)
}
const createFilter = (queryString: string) => {
	return (restaurant: RestaurantType) => {
		return (
			restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) >= 0
		)
	}
}

let tableDataCopy: TableDataInitType
const searchFn = () => {
	// 备份数据用于查找结果后的数据恢复
	tableDataCopy = JSON.parse(JSON.stringify(tableData))
	if(querySearchKey.value === '' || querySearchKey.value === undefined) return ElMessage.error('查询内容不能为空')
	updateTableDataEventFn({
		updateTableDataFlag: 'search',
		searchKey: querySearchKey.value.toLowerCase()
	})
}
const updateTableDataEventFn = ({
	updateTableDataFlag = '',
	searchKey
}: {
	updateTableDataFlag: string
	searchKey?: string
}) => {
	if(updateTableDataFlag === 'search') {
		const data = tableDataCopy.data.filter(item => {
			if(item?.key?.toLowerCase()?.includes(searchKey!)) return item
		})

		tableData.data = data
		tableData.currentPage = 1
		tableData.total = tableData.data.length
	} 
	else {
		queryServiceConfigListFn(mainParams.serviceName)
	}
} 

// 监听搜索框，当值搜索框的值清空时，恢复
watch(() => querySearchKey.value, newValue => {
	// 恢复 el-autocomplete 下拉选择框的值
	if(newValue === '') updateTableDataEventFn({updateTableDataFlag: 'reset'})
})

// dialogType = view, add, edit, othres
const dialogConfig: DialogConfigType  = reactive({
	dialogVisible: false,
	dialogType: '',
	title: '',
	width: 0,
	row: {},
	dialoFootFlag: true
})

// 预览/新增/编辑弹窗设置
const setDialogConfigFn = (dialogConfigFnParams: DialogConfigType ) => {
	Object.assign(dialogConfig, dialogConfigFnParams, {activeTab: mainParams.activeTab})
	const dialogTarget = dialogConfig.dialogTarget
	if(dialogConfig.dialogType === DIALOG_TYPE_VIEW) dialogTarget.exposeOpenDialogViewFn(dialogConfig)
	else if(dialogConfig.dialogType === DIALOG_TYPE_ADD || dialogConfig.dialogType === DIALOG_TYPE_EDIT) dialogTarget.exposeOpenDialogAdd_EditFn(dialogConfig)
	else dialogTarget.exposeOpenDialogOthersFn(dialogConfig)
}

// 预览
const tableDataViewEventFn = (row: RowType): void => setDialogConfigFn({
	dialogVisible: true, 
	dialogType: DIALOG_TYPE_VIEW, 
	dialogTarget: dialogRowViewRef,
	title: `${mainParams.activeTab === VERSION_TAB[0] ? '主' : '灰度'}版本预览`, 
	width: 800,
	row,
	dialoFootFlag: false
})

// 新增
const tableDataAddEventFn = (): void  => setDialogConfigFn({
	dialogVisible: true, 
	dialogType: DIALOG_TYPE_ADD, 
	dialogTarget: dialogAddEditRef,
	title: `${mainParams.activeTab === VERSION_TAB[0] ? '主' : '灰度'}版本新增`, 
	width: 800,
	row: {},
	dialoFootFlag: true
})

// 编辑
const tableDataEditEventFn = (row: RowType): void => setDialogConfigFn({
	dialogVisible: true, 
	dialogType: DIALOG_TYPE_EDIT, 
	dialogTarget: dialogAddEditRef,
	title: `${mainParams.activeTab === VERSION_TAB[0] ? '主' : '灰度'}版本编辑`, 
	width: 800,
	row,
	dialoFootFlag: true
})

// 新增/编辑 确认
const confirmSubmitEventFn = async (row: RowType) => {
	// 调用接口，提交数据
	let res: ResponseType = {code: -1, msg: '', data: [], total: -1} 
	const params = {
		sys_name: SYS_NAME,
		service_name: mainParams.serviceName,
		...row
	}
	if(dialogConfig.dialogType === DIALOG_TYPE_ADD) {
		res = mainParams.activeTab === VERSION_TAB[0]
			? await serviceDycofigMainAddRqs(params)
			: await serviceDycofigGrayAddRqs(params)
	}
	if(dialogConfig.dialogType === DIALOG_TYPE_EDIT) {
		res = mainParams.activeTab === VERSION_TAB[0]
			? await serviceDycofigMainEditRqs(params)
			: await serviceDycofigGrayEditRqs(params)
	}
	if(res?.code === REQUEST_SUCCESS_NO) {
		ElMessage.success(res.msg)
	} else {
		ElMessage.error(res.msg)
	}
	// 更新页面数据
	queryServiceConfigListFn(mainParams.serviceName)
	dialogAddEditRef.value?.exposeCloseDialogAdd_EditFn()
}

// 删除，从表格组件 TableOperation.vue 过来
// 删除单条数据 $emit('handleDeleteEvent', row)
// 全删 $emit('handleDeleteEvent', null, true)
const tableDataDeleteEventFn = (rows: RowType, isMultipleDeletetFlag: boolean = false): void => {
	ElMessageBox.confirm(
		'数据将被永久删除，是否确认删除？',
		'删除提示',
		{
			confirmButtonText: '确定',
			cancelButtonText: '取消',
			type: 'warning',
		}
	).then(async () => {
		const keys = isMultipleDeletetFlag ? rows.map((item: RowType) => item.key) : [rows.key]
		const params = {key: keys, sys_name: SYS_NAME, service_name: mainParams.serviceName}
		const res = mainParams.activeTab === VERSION_TAB[0]
			? await serviceDycofigMainDeleteRqs(params)
			: await serviceDycofigGrayDeleteRqs(params)
		
		if(res?.code === REQUEST_SUCCESS_NO) {
			ElMessage.success(res.msg)
			queryServiceConfigListFn(mainParams.serviceName)
		}
	}).catch(() => {
		ElMessage({
			type: 'info',
			message: '删除操作已取消',
		})
	})
}

// 翻页，更新当前页对应的数据
const tableDataUpdateEventFn = () => {
	// 单独记录每个服务实例对应的分页状态
	mainParams.serviceList.forEach((item => {
		if(item.service_name === mainParams.serviceName) {
			const isTabMainFlag = VERSION_TAB[item.versionTab!] === VERSION_TAB[0]
			const activeTabType = isTabMainFlag ? TAB_MAIN : TAB_GRAY
			if(mainParams.activeTab === VERSION_TAB[item.versionTab!]) {
				if(item.tabRecode) item.tabRecode[activeTabType] = {
					currentPage: tableData.currentPage,
					pageSize: tableData.pageSize
				}
			}
		}
	}))

	queryServiceConfigListFn(mainParams.serviceName)
}

onMounted(() => {
	queryServiceListFn()

	// 批量删除, isMultipleDeletetFlag 是否批量删除操作
	$mitt.on('TABLE_MULTIPLE_DELETE_EVENT', rows => {
		const isMultipleDeletetFlag = true
		tableDataDeleteEventFn(rows, isMultipleDeletetFlag)
	})
})

onBeforeUnmount(() => {
	$mitt.all.delete('TABLE_MULTIPLE_DELETE_EVENT')
})
</script>

<template>
	<ul class="service-bar list-inline child-mr-15 mb-20">
		<li 
			v-for="(item, index) in mainParams.serviceList" 
			:key="index" 
			:class="[`bg-${item.bgColor} ${mainParams.serviceIndex === index ? 'active bg-white' : ''}`]" 
		>
			<div 
				class="service-item" 
				:class="[`bg-${item.bgColor} ${mainParams.serviceIndex === index ? 'active' : ''}`]" 
				@click="queryServiceConfigListFn(item.service_name)" 
			>
				<div class="desc" :title="item.service_name" :alt="item.service_name">
					{{ item.service_name }}
				</div>
			</div>
		</li>
	</ul>
	
	<div class="operation-bar">
		<div>
			<el-form class="search-bar" @submit.prevent>
				<span class="search-item">
					<el-autocomplete 
						v-model="querySearchKey" 
						:fetch-suggestions="querySearch" 
						clearable 
						placeholder="请输入配置项的 Key 值" 
						@keyup.enter="searchFn" 
					>
						<!-- <template #suffix>
							<el-icon class="el-input__icon" @click="querySearch">
								<edit />
							</el-icon>
						</template> -->
					</el-autocomplete>
				</span>
				<el-button 
					type="primary" 
					:class="[`btn btn-lg btn-${THEME_COLOR}`]" 
					v-preventReClick 
					v-auth 
					@click="searchFn" 
				>搜 索</el-button>
		
				<el-button 
					type="primary" 
					:class="[`btn btn-${THEME_COLOR}`]" 
					v-preventReClick 
					@click="tableDataAddEventFn" 
				>
					<el-icon><Plus /></el-icon>
					{{ mainParams.addServiceConfigName }}
				</el-button>
			</el-form>
		</div>
		<MultipleOperation :multipleConfig="mainParams.multipleConfig" width="1.4rem" />
	</div>

	<div class="tab-bar">
		<el-tabs
			v-model="mainParams.activeTab" 
			type="card" 
			@tab-click="tabHandleClick" 
		>
			<el-tab-pane v-for="(itme, index) in tabs" :key="index" :label="itme.label" :name="itme.name">
				<template v-if="mainParams.activeTab === itme.name">
					<TableOperation 
						:tableHeaderColumns="mainParams.activeTab === VERSION_TAB[ZERO] ? tableHeaderColumnsMain : tableHeaderColumnsGray" 
						v-model:tableData="tableData" 
						@TABLE_DATA_SELECT_EVENT="TABLE_DATA_SELECT_EVENT_FN(tableData.data)" 
						@TABLE_DATA_UPDATE_EVENT="tableDataUpdateEventFn" 
						@TABLE_DATA_VIEW_EVENT="tableDataViewEventFn" 
						@TABLE_DATA_EDIT_EVENT="tableDataEditEventFn" 
						@TABLE_DATA_DELETE_EVENT="tableDataDeleteEventFn" 
					/>
				</template>
			</el-tab-pane>
		</el-tabs>
	</div>

	<DialogRowView ref="dialogRowViewRef" />
	<DialogRowAddEdit ref="dialogAddEditRef" @CONFIRM_SUBMIT_EVENT="confirmSubmitEventFn" />
</template>

<style lang="scss" scoped>
.service-bar {
	display: -webkit-flex;
	display: flex;
	flex-wrap: wrap;

	li {
		margin-bottom: .1rem;
		padding: .04rem;
		border-radius: .1rem;
		border: .02rem solid transparent;
		&.active {
			border-color: $color-night;
		}
	}
	.service-item {
		position: relative;
		display: -webkit-flex;
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		padding: .15rem;
		height: .7rem;
		border-radius: .1rem;
		font-size: .24rem;
		cursor: pointer;
		overflow: hidden;

		.desc {
			font-size: .16rem;
		}

		&.active {
			color: $color-night;
			.current-icon {
				display: block;
			}
		}
	}
}

.search-bar {
	margin-bottom: .2rem;
	:deep(.search-item) {
		margin-right: .15rem;
		input.el-input__inner {
			width: 2.94rem;
		}
		.el-input__suffix {
			position: absolute;
			right: .05rem;
		}
	}
}
</style>